//
// Created by Administrator on 2024/6/11.
//变量
//
#include "stdio.h"
//源程序开头位置引用性声明，整个文件都可以使用。
extern int test_a;
#define PR printf
#define NL "\n"
#define D "%d"
#define D1 D NL
#define D2 D D NL
#define D3 D D D NL
#define D4 D D D D NL

/**
 * 7.9变量的存储类别
 * 7.9.1动态存储方式与静态存储方式
    根据变量存在的时间(或变量分配的时间或变量分配的物理位置)的不同，可以将变量分为静态存储方式和动态存储方式两大类。
     一个程序在运行时，操作系统分配给它的存储空间可以分为三大部分：程序代码区、静态存储区、动态存储区。
     全局变量和静态局部变量存于静态存储区，在编译时就确定(程序加载时分配)了，到程序运行结束才释放，
     而形参和未加static的局部变量一般都存储于动态存储区，是在函数调用时才分配，在函数调用结束时就释放。
     决定变量的存储方式与变量定义的位置(决定全局变量和局部变量)和变量定义的存储类别(决定static和非static)有关
     存储类别 数据类型 变量名;
变量有四种存储类别：auto(自动)、extern(外部、外面)、static(静态)、register(寄存器)；变量有多种数据类型，如int,long,char,float等。
1.auto变量
形参和局部变量定义时默认“auto”存储类别。auto变量每次函数调用时都分配存储空间并赋初值，在函数调用结束时就释放
2. 用static声明局部变量
 用static声明的局部变量是静态局部变量，在编译时确定存储空间并赋初值，在函数调用时不再分配存储空间和赋初值，
 在函数调用结束时也不释放存储空间，因此，该类变量始终保留上次函数调用结束时的值。但因其为局部变量，退出其所定义的函数后是不可用的
    用static声明外部变量
    定义全局变量时若指定存储类别为static，则意味着该变量只限于本文件中使用，而不能在其它文件中引用。
3. register变量
    系统考虑到内存单元的访问速度远低于CPU中寄存器的访问速度，而某些变量的使用频率很高，若能用寄存器作为变量分配的存储空间，对程序执行的效率将可以大大提高。
    因此，编译器允许以寄存器作为变量分配的存储空间，
    只要在定义变量时将其存储类别声明为register即可。但由于CPU中的寄存器数目有限，多数系统register变量按auto变量处理
4. 用extern声明外部变量
 单词extern本来是指外部或外面的意思，在C语言中表示声明变量在函数外面或本文件外面定义，即变量的引用性声明，不是定义，不能赋初值，声明位置在函数外或函数内，不分配存储空间，
 数据类型是int可以省略；也可以指这是在函数外面定义的变量，即变量的定义性声明，且可赋初值，定义位置在函数外，有分配存储空间。全局变量默认extern类型。


 内部函数和外部函数
 7.10.1内部函数
函数定义时声明为static类别的函数，意味着该函数只限于本文件中使用，而不能在其它文件中引用。
7.10.2外部函数
函数定义时声明为extern类别的函数，意味着该函数可在本文件中使用，也在其它文件中引用。默认定义的都是extern类别的函数。

 * @return
 */

void test_variable(){
    auto int a=2;
    static int b=3;
    a++;b++;
    printf("a=%d,b=%d\n",a,b);
}

//利用静态局部变量保留上次函数调用结束时的值求1到5的阶乘
int fact(int n){
    static int f= 1;
    f=f*n;
    return f;
}

//函数内引用性声明，只有有声明的函数可以使用
int fun(){
    return test_a;
}
//函数内引用性声明，只有有声明的函数可以使用。
void fun1(){
    /*没有对函数外变量n的引用性声明，所以此处不使用变量n */
}

//利用宏实现替换函数名和字符串常量


int main3(){
    test_variable();
    test_variable();
    test_variable();


    for(int i=1;i<=5;i++)
        printf("%d!=%d\n",i, fact(i));

    printf("------------------------------\n");
    //源程序开头位置引用性声明，整个文件都可以使用。
    int test_a=5;
    printf("%d,%d\n",fun(),test_a);

    extern int test_n; /* 函数内引用性声明，引用位置在函数外面 */
    printf("function out's varible test_n=%d \n",test_n);

    PR(D1,1); PR(D2,1,2); PR(D3,1,2,3); PR(D4,1,2,3,4);

    return 0;
}
int test_a=10; /*或extern int a=10;函数外面定义全局变量a,也可将此语句置于工程的其它文件中定义*/
extern int test_n=6; /*或 int n=6; 或extern n=6;*/  /* 函数外面定义全局变量n */